﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Windows.Forms;
using LevelEditor.Document;
using LevelEditor.View;

namespace LevelEditor.Forms
{
    public partial class LayerViewControl : Control
    {
        #region Fields

        MainForm owner;

        #endregion

        #region Properties

        /// <summary>
        /// Grid visibility. True = visible.
        /// </summary>
        [Category("Appearance")]
        [Description("Grid is visible")]
        [DefaultValue(true)]
        public bool GridVisible { get; set; }

        /// <summary>
        /// Thickness of the grid lines.
        /// </summary>
        [Category("Appearance")]
        [Description("Thickness of the grid lines.")]
        [DefaultValue(1)]
        public decimal GridThickness { get; set; }

        [Browsable(false)]
        public Rectangle SelectionTiles { get; private set; }

        [Browsable(false)]
        public Rectangle SelectionRectangle { get; private set; }

        [Browsable(false)]
        public List<LayerView> Views { get; set; }

        public enum PaintTool { PENCIL, BUCKET, TILEPICKER, ERASER }

        public PaintTool Tool { get; set; }

        #endregion

        #region Constructors

        public LayerViewControl(MainForm _owner)
        {
            InitializeComponent();

            GridVisible = true;
            GridThickness = 1;

            owner = _owner;

            Views = new List<LayerView>();
            foreach (Layer layer in owner.Level.Layers)
                Views.Add(new LayerView(layer));

            SetStyle(ControlStyles.UserPaint | ControlStyles.AllPaintingInWmPaint |
                ControlStyles.OptimizedDoubleBuffer | ControlStyles.ResizeRedraw |
                ControlStyles.Opaque, true);
        }

        #endregion

        #region Methods

        public void Clear()
        {
            Views.Clear();
            foreach (Layer layer in owner.Level.Layers)
                Views.Add(new LayerView(layer));
            Invalidate();
        }

        public void Reset()
        {
            while (Views.Count > owner.Level.Layers.Count)
                Views.RemoveAt(Views.Count - 1);
            while (Views.Count < owner.Level.Layers.Count)
                Views.Add(new LayerView(owner.Level.Layers[Views.Count]));
            foreach (LayerView lv in Views)
                lv.Reset();
            int largestX = 0, largestY = 0, layerX, layerY;
            for (int i = 0; i < Views.Count; ++i)
            {
                layerX = Views[i].Size.Width * owner.Level.Layers[i].TileSize.Width + 1;
                layerY = Views[i].Size.Height * owner.Level.Layers[i].TileSize.Height + 1;
                if (largestX < layerX) largestX = layerX;
                if (largestY < layerY) largestY = layerY;
            }
            Size = new Size(largestX, largestY);
            Invalidate();
        }

        public void LayerSizeChanged()
        {
            foreach (LayerView lv in Views)
                lv.CheckSize();
            int largestX = 0, largestY = 0, layerX, layerY;
            for (int i = 0; i < Views.Count; ++i)
            {
                layerX = Views[i].Size.Width * owner.Level.Layers[i].TileSize.Width + 1;
                layerY = Views[i].Size.Height * owner.Level.Layers[i].TileSize.Height + 1;
                if (largestX < layerX) largestX = layerX;
                if (largestY < layerY) largestY = layerY;
            }
            Size = new Size(largestX, largestY);
            Invalidate();
        }

        #endregion

        #region Events

        private void LayerViewControl_Paint(object sender, PaintEventArgs e)
        {
            e.Graphics.Clear(BackColor);
            for (int i = 0; i < Views.Count; ++i)
            {
                if (owner.Level.Layers[i].Visible)
                {
                    Views[i].Draw(e.Graphics);
                }
            }

            // draw the grid
            if (GridVisible && owner.Level.Layers.Count > 0)
            {
                Pen gridPen = new Pen(ForeColor, Convert.ToSingle(GridThickness));
                Size tileSize = owner.Level.Layers[owner.CurrentLayer].TileSize;
                for (int x = 0; x <= owner.Level.Layers[owner.CurrentLayer].Size.Width; ++x)
                {
                    e.Graphics.DrawLine(gridPen, new Point(x * tileSize.Width, 0),
                        new Point(x * tileSize.Width, tileSize.Height * owner.Level.Layers[owner.CurrentLayer].Size.Height));
                }
                for (int y = 0; y <= owner.Level.Layers[owner.CurrentLayer].Size.Height; ++y)
                {
                    e.Graphics.DrawLine(gridPen, new Point(0, y * tileSize.Height),
                        new Point(tileSize.Width * owner.Level.Layers[owner.CurrentLayer].Size.Width, y * tileSize.Height));
                }
                gridPen.Dispose();
            }

            // draw selection box
            if (SelectionTiles != Rectangle.Empty && owner.Level.Layers.Count > 0)
            {
                Pen selectionPen = new Pen(Color.Magenta, 5f);
                e.Graphics.DrawRectangle(selectionPen, SelectionRectangle);

                selectionPen.Dispose();
            }
        }

        private void LayerViewControl_MouseMove(object sender, MouseEventArgs e)
        {
            Size tileSize = owner.Level.Layers[owner.CurrentLayer].TileSize;
            PaletteControl pc = (owner.Palette.tabs.SelectedTab.Controls[0] as PaletteControl);
            if (Tool != PaintTool.ERASER)
                SelectionTiles = new Rectangle(e.X / tileSize.Width, e.Y / tileSize.Height, pc.SelectedTiles.Width, pc.SelectedTiles.Height);
            else
                SelectionTiles = new Rectangle(e.X / tileSize.Width, e.Y / tileSize.Height, 1, 1);
            SelectionRectangle = new Rectangle(SelectionTiles.X * tileSize.Width, SelectionTiles.Y * tileSize.Height,
                    SelectionTiles.Width * tileSize.Width, SelectionTiles.Height * tileSize.Height);
            Invalidate();
        }

        #endregion

    }
}
